import org.apache.commons.lang3.ArrayUtils;
import org.junit.Test;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 日期类
 * git地址

 https://gitee.com/yujianlong1988/java8andDisruptor.git
 * @author yujianlong
 * @create 2018-06-16 11:29
 **/
public class DateTest1 {

	@Test
	public void localDateTest1() {//初始化
		//当前日期
		LocalDate now = LocalDate.now();
		System.out.println(now);
		//指定日期1
		LocalDate now1 = LocalDate.of(2018, 6, 18);
		System.out.println(now1);
		LocalDate parseDate = LocalDate.parse("2018-06-18", DateTimeFormatter.ofPattern("yyyy-MM-dd"));//线程安全和
		System.out.println(parseDate);
	}

	@Test
	public void localDateTest2() {//报异常1 -做法1
		DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

		List<String> dateList = IntStream.rangeClosed(10, 28).boxed().map(i -> "2018-06-" + i).collect(Collectors.toList());
		dateList.parallelStream().forEach(s->{//报异常
			try {
				Date date = sdf.parse(s);
				System.out.println(date);
			} catch (ParseException e) {
				e.printStackTrace();
			}

		});

	}
	@Test
	public void localDateTest3() {//报异常1 -传统做法
		DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

		List<String> dateList = IntStream.rangeClosed(10, 28).boxed().map(i -> "2018-06-" + i).collect(Collectors.toList());
		List<Runnable> runnables = dateList.stream().map(s -> (Runnable) () -> {
			try {
				Date date = sdf.parse(s);
				System.out.println(date);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}).collect(Collectors.toList());//用到强转
		ExecutorService executorService = Executors.newCachedThreadPool();
		for (Runnable r:runnables){
			executorService.execute(r);
		}


		executorService.shutdown();
		try {
			executorService.awaitTermination(10, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void localDateTest4() {//不报异常1 -传统做法
		DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

		List<String> dateList = IntStream.rangeClosed(10, 28).boxed().map(i -> "2018-06-" + i).collect(Collectors.toList());
		List<Runnable> runnables = dateList.stream().map(s -> (Runnable) () -> {
			LocalDate parseDate = LocalDate.parse(s, sdf);//线程安全和
			System.out.println(parseDate);
		}).collect(Collectors.toList());//用到强转
		ExecutorService executorService = Executors.newCachedThreadPool();
		for (Runnable r:runnables){
			executorService.execute(r);
		}
		executorService.shutdown();
		try {
			executorService.awaitTermination(10, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void localDateTest6() {//不报异常1 -传统做法（结局报异常的方法就是线程封闭）


		List<String> dateList = IntStream.rangeClosed(10, 28).boxed().map(i -> "2018-06-" + i).collect(Collectors.toList());
		List<Runnable> runnables = dateList.stream().map(s -> (Runnable) () -> {
			DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			try {
				Date date = sdf.parse(s);
				System.out.println(date);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}).collect(Collectors.toList());//用到强转
		ExecutorService executorService = Executors.newCachedThreadPool();
		for (Runnable r:runnables){
			executorService.execute(r);
		}
		executorService.shutdown();
		try {
			executorService.awaitTermination(10, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void localDateTest5() {//不报异常1 -java8做法
		DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

		List<String> dateList = IntStream.rangeClosed(10, 28).boxed().map(i -> "2018-06-" + i).collect(Collectors.toList());
		dateList.parallelStream().forEach(s->{//报异常
			LocalDate parseDate = LocalDate.parse(s, sdf);//线程安全和
			System.out.println(parseDate);

		});
	}

//以上就是java日期类的线程安全问题，主要在于格式化类
	@Test
	public void localDateTest7() {//获取年月日信息
		LocalDate now = LocalDate.now();
		System.out.println(now.getYear());
		System.out.println(now.getMonth().getValue());
		System.out.println(now.getDayOfMonth());
		System.out.println(now.isLeapYear());
		System.out.println(now.lengthOfMonth()); //本月有多少天
		System.out.println(now.lengthOfYear());//本年多少天

		LocalDate assignDate = now.withYear(2019).withDayOfMonth(3).withMonth(7);//指定日期
		System.out.println(assignDate);
		System.out.println(now);
		LocalDate plusDate = now.plusDays(4);
		System.out.println(plusDate);

		//另一种方式获取年月日
		int year = now.get(ChronoField.YEAR);
		int month = now.get(ChronoField.MONTH_OF_YEAR);
		int day = now.get(ChronoField.DAY_OF_MONTH);
		System.out.println(year);
		System.out.println(month);
		System.out.println(day);
	}
	@Test
	public void localDateTest8() {//比较日期大小
		LocalDate now = LocalDate.now();
		LocalDate tdate = LocalDate.of(2018, 7, 22);
		boolean isAfter = now.isAfter(tdate);
		boolean isbefore = now.isBefore(tdate);
		System.out.println(isAfter);
		System.out.println(isbefore);

		int com = now.compareTo(tdate);//可以返回相差天数now-tdate
		System.out.println(com);

		int com1 = tdate.compareTo(now);//可以返回相差天数tdate-now
		System.out.println(com1);

	}

	@Test
	public void localDateTest9() {//计算时间间隔
		LocalDate now = LocalDate.now();
		LocalDate tdate = LocalDate.of(2018, 6, 9);
		Duration between = Duration.between(now.atStartOfDay(), tdate.atStartOfDay());
		System.out.println(between.toDays());//可能会产生负数，而不是返回绝对值 对于LocalDate 只有大于天为单位才有意义
		//Duration只针对localdatetime起作用

		Period between1 = Period.between(now, tdate);
		System.out.println(between1.getDays());//LocalDate 可以用Period来计算相差天数 也可能会产生负数
		System.out.println(between1.getMonths());
		System.out.println(between1.getYears());
		System.out.println(between1.negated().getDays());

		//方法三
		long between2 = ChronoUnit.DAYS.between(now, tdate);
		System.out.println(between2);
		long between3 = ChronoUnit.MONTHS.between(now, tdate);
		System.out.println(between3);
	}

	//下边做个练习 获取时间段之间的每一天（比如我们要分别查询数据库中每一天的记录，并发执行提升效率等场景）
	@Test
	public void localDateTest10(){
		//2018-06-18到2018-07-07

		LocalDate parseDate = LocalDate.parse("2018-06-18", DateTimeFormatter.ofPattern("yyyy-MM-dd"));//线程安全和
		LocalDate targetDate = LocalDate.parse("2018-07-07", DateTimeFormatter.ofPattern("yyyy-MM-dd"));//线程安全和

		//计算时间间隔
		long between = ChronoUnit.DAYS.between(parseDate, targetDate);
		System.out.println(between);

		LocalDate[] seed=new LocalDate[]{parseDate,parseDate.plusDays(1)};
		System.out.println(ArrayUtils.toString(seed));
		//还记斐波那契数列吗，原理就是种下一颗种子 打印每一天
		List<LocalDate> collect = Stream.iterate(seed, t -> new LocalDate[]{t[1], t[1].plusDays(1)})
				.limit(between+1).map(t -> t[0]).collect(Collectors.toList());
		collect.stream().forEach(System.out::println);

		//打印时间段
		Stream.iterate(seed, t -> new LocalDate[]{t[1], t[1].plusDays(1)})
				.limit(between)
				.forEach(arra->{

					System.out.println(arra[0]+"#"+arra[1]);
				});

	}

		public static void main(String[]args)
		{
			int x =5,y=10; //定义两个变量
			int temp = x;
			x = y;
			y = temp;
			System.out.println("x="+x+"y="+y);

		}


	//下边做个练习 获取时间段之间的每一天（比如我们要分别查询数据库中每一天的记录，并发执行提升效率等场景）
	@Test
	public void localDateTimeTest11(){//计算00:00:00 到23：59：59的所有时间段
		//2018-06-18到2018-07-07
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime parseDate = LocalDateTime.parse("2018-06-18 00:00:00",dateTimeFormatter);
		LocalDateTime targetDate = LocalDateTime.parse("2018-05-07 23:59:59", dateTimeFormatter);



		//计算时间间隔
		long between = ChronoUnit.DAYS.between(parseDate, targetDate);
		System.out.println(between);

		if (between<0) {
			LocalDateTime tmp=parseDate;
			parseDate=targetDate ;
			targetDate = tmp;


			between = 0 - between;
		}

		LocalDateTime[] seed=new LocalDateTime[]{parseDate,parseDate.withHour(23).withMinute(59).withSecond(59)};
		System.out.println(ArrayUtils.toString(seed));
		//还记斐波那契数列吗，原理就是种下一颗种子 打印每一天
		List<LocalDateTime> collect = Stream.iterate(seed, t -> new LocalDateTime[]{t[0].plusDays(1), t[1].plusDays(1)})
				.limit(between+1).map(t -> t[0]).collect(Collectors.toList());
		collect.stream().map(dateTimeFormatter::format).forEach(System.out::println);

		//打印时间段
		Stream.iterate(seed, t -> new LocalDateTime[]{t[0].plusDays(1), t[1].plusDays(1)})
				.limit(between+1)
				.forEach(arra->{

					System.out.println(dateTimeFormatter.format(arra[0])+"#"+dateTimeFormatter.format(arra[1]));
				});

	}

	@Test
	public void temporalAjustorTest1(){//获取月末或下一个周六
//		LocalDate now = LocalDate.now();
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		LocalDate now = LocalDate.parse("2018-06-15",dateTimeFormatter);
		System.out.println(now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY)));
		System.out.println(now.with(TemporalAdjusters.previousOrSame(DayOfWeek.SATURDAY)));//上个周六
		System.out.println(now.with(TemporalAdjusters.lastDayOfMonth()));//月末
		System.out.println(now.with(TemporalAdjusters.lastDayOfYear()));//年末
		System.out.println(now.with(TemporalAdjusters.dayOfWeekInMonth(2,DayOfWeek.FRIDAY)));//本月第二个周五
		System.out.println(now.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)));//本月最后一个周五

		//TemporalAdjuster 是函数式接口
		//计算下一个工作日
		TemporalAdjuster nextWorkDay=temporal->{

			int dayOfweek = temporal.get(ChronoField.DAY_OF_WEEK);//今天这周的周几
			int day2Add=1 ;//正常天数就是下一天 加一就好
			if(DayOfWeek.FRIDAY.getValue()==dayOfweek){
				day2Add=3;
			}else if (DayOfWeek.SATURDAY.getValue()==dayOfweek){
				day2Add=1;
			}
			return temporal.plus(day2Add,ChronoUnit.DAYS);
		};

		LocalDate workDay = now.with(nextWorkDay);
		System.out.println(workDay);

	}


	@Test
	public void transferTest1() {//相互之间转换
		//LocalDate转LocalDateTime
		LocalDateTime localDateTime = LocalDate.now().atStartOfDay();//LocalDate转LocalDateTime
		//localdate转date
		Date from = Date.from(LocalDateTime.now().toInstant(ZoneOffset.of("+8")));

		//date转localdate
		LocalDate localDate1 = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

		//timestamp转localdateTime
		new Timestamp(System.currentTimeMillis()).toLocalDateTime();
		//localdateTime转timestamp
		Timestamp.valueOf(LocalDateTime.now());


		//localdateTime转long时间戳
		LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
		//或者
		Timestamp.valueOf(LocalDateTime.now()).getTime();

		//sql.date 转localdate
		new java.sql.Date(System.currentTimeMillis()).toLocalDate();
		//localdate转sql.date
		java.sql.Date.valueOf(LocalDate.now());

		//DateTimeFormatter转format
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		Format farmat=dateTimeFormatter.toFormat();

	}


}
